#include "MainLayer.h"
#include "Bullet.h"
#include "EffectManager.h"
#include "EffectDefine.h"
#include "Effect.h"
#include "EffectFactory.h"
#include "GameConfig.h"
#include "BulletsBank.h"
#include "WeaponBank.h"
#include "BulletFactory.h"
#include "Config.h"
#include "PlaneBank.h"
#include "PlaneFactory.h"
#include "StrategyBank.h"
#include "EnemyBank.h"
#include "PetsBank.h"
#include "PetFactory.h"
#include "ItemProcessorBank.h"
#include "Item.h"
#include "ItemBank.h"
#include "EnemyActionFactory.h"
#include "PoolObject.h"
#include "MathUtil.h"
#include "GlobalData.h"
#include "MainScene.h"
#include "TestGameScene.h"
#include "InputLayer.h"
#include "ResultDialog.h"
#include "ShadowLayer.h"

#define SHADOW_LAYER -1
#define PLANE_LAYER 0
#define ITEM_LAYER 1
#define UI_LAYER 2

MainLayer::MainLayer(void)
{
	_myPlant = NULL;
	_pet1 = NULL;
	_pet2 = NULL;
	_listPlayerBullet = NULL;
	_listEnemyBullet = NULL;
	_listEnemy = NULL;
	_listItem = NULL;
	_enemyManager = NULL;
	_effectManager = NULL;
	_map = NULL;

	_score = 0;
	_star = 0;
	_kilomet = 0;
	_isPause = false;
}


MainLayer::~MainLayer(void)
{
	// Shared init

	// Clear PoolObject
	PoolObject<Bullet>::sharedPoolObject()->clearPool();
	PoolObject<Enemy>::sharedPoolObject()->clearPool();

	CC_SAFE_RELEASE(_myPlant);
	CC_SAFE_RELEASE(_pet1);
	CC_SAFE_RELEASE(_pet2);
	CC_SAFE_RELEASE(_enemyManager);
	CC_SAFE_RELEASE(_effectManager);
	CC_SAFE_RELEASE(_listPlayerBullet);
	CC_SAFE_RELEASE(_listEnemyBullet);
	CC_SAFE_RELEASE(_listEnemy);
	CC_SAFE_RELEASE(_listItem);
	CC_SAFE_RELEASE(_map);
}

bool MainLayer::init()
{
	if (!CCLayer::init())
		return false;

	CCRect bound = BULLET_AREA;
	setBulletArea(bound);
	initGameElement();
	initUI();

	this->setKeypadEnabled(true);
	//CCTextureCache::sharedTextureCache()->dumpCachedTextureInfo();
	return true;
}

void MainLayer::initGameElement()
{
	// Shared init
	
	
	setMap(Map::create());

	addChild(_map);
	////// Enemy
	setEnemies(CCArray::create());
	setEnemyBullets(CCArray::create());
	setPlayerBullets(CCArray::create());
	setItems(CCArray::create());

	////// Init plant
	PlayerData* playerData = GlobalData::sharedData()->getPlayerData();
	PlaneFactory* pF = PlaneBank::sharedPlaneBank()->getPlaneFactoryById((char*)playerData->getPlaneId()->getCString());
	PlayerPlane* plane = pF->createPlaneByLevel(playerData->getPlaneLevel());

	float x = CCEGLView::sharedOpenGLView()->getDesignResolutionSize().width / 2;
	plane->setPosition(x, 0 + 100);
	setMyPlant(plane);
	addChild(plane, PLANE_LAYER);

	_myPlant->setMaxHealth(pF->getPlaneDataByLevel(playerData->getPlaneLevel())->getHealth());

	// Enemy manager
	EnemyManager* eManager = EnemyManager::create();
	setEnemyManager(eManager);
	addChild(eManager);
	// Effect manager
	EffectManager* efManager = EffectManager::create();
	setEffectManager(efManager);
	addChild(efManager, ITEM_LAYER);
	// Shadow layer
	ShadowLayer* shadowLayer = ShadowLayer::create();
	shadowLayer->setPosition(ccp(70, -70));
	addChild(shadowLayer);
	//
	Pet* pig1 = (PetBank::sharedPetBank()->getPetFactory((char*)playerData->getPetType()->getCString()))->createPet();
	pig1->setPlane(_myPlant);
	pig1->setOffset(ccp(-50 - pig1->boundingBox().size.width, 50));
	//pig1->setWeaponLevel(1);
	addChild(pig1, PLANE_LAYER);
	setPet1(pig1);

	Pet* pig2 = (PetBank::sharedPetBank()->getPetFactory((char*)playerData->getPetType()->getCString()))->createPet();
	pig2->setPlane(_myPlant);
	pig2->setOffset(ccp(plane->boundingBox().size.width + 50, 50));
	//pig2->setWeaponLevel(1);
	addChild(pig2, PLANE_LAYER);
	setPet2(pig2);

	float angle = MathUtil::angle2Vetor(ccp(1, 0), ccp(0, 1));
	CCPoint test = MathUtil::rotateVector(ccp(1, 0), M_PI/2);
}

void MainLayer::initUI()
{
	// Init player health bar
	
}

void MainLayer::removeEnemyBullet( Bullet* bullet )
{
	_listEnemyBullet->removeObject(bullet);
	removeChild(bullet);
}

void MainLayer::update( float dt )
{
	// Check collision
	int i = 0, j = 0;
	//////////////////////////////////////////////////////////////////////////
	// PLAYER BULLET
	//////////////////////////////////////////////////////////////////////////
	
	while (i < _listPlayerBullet->count())
	{
		Bullet* bullet = dynamic_cast<Bullet*>(_listPlayerBullet->objectAtIndex(i));
		// Update position
		bullet->updatePosition(dt);

		if (!bullet->boundingBox().intersectsRect(_bulletArea))
		{
			removePlayerBullet(bullet);
			continue;
		}

		// Check collision with enemy
		j = 0;
		while (j < _listEnemy->count())
		{
			Enemy* enemy = dynamic_cast<Enemy*>(_listEnemy->objectAtIndex(j));

			if (bullet->boundingBox().intersectsRect(enemy->boundingBox()))
			{
				enemy->onShot(bullet);
				bullet->onShot(enemy);
				removePlayerBullet(bullet);
				i--;
				break;
			}
			j++;
		}
		i ++;
	}

	//////////////////////////////////////////////////////////////////////////
	// ENEMY BULLET
	//////////////////////////////////////////////////////////////////////////
	i = 0;
	while (i < _listEnemyBullet->count())
	{
		Bullet* bullet = dynamic_cast<Bullet*>(_listEnemyBullet->objectAtIndex(i));
		// Update position
		bullet->updatePosition(dt);
		if (!bullet->boundingBox().intersectsRect(_bulletArea))
		{
			removeEnemyBullet(bullet);
			continue;
		}

		// Check collision with Plane
		if (bullet->boundingBox().intersectsRect(_myPlant->boundingBox()))
		{
			_myPlant->onShot(bullet);
			bullet->onShot(_myPlant);
			removeEnemyBullet(bullet);
			i--;
			break;
		}


		i++;
	}

	/* ITEM */
	i = 0;
	while (i < _listItem->count())
	{
		CCObject* a = _listItem->objectAtIndex(i);
		Item* item = dynamic_cast<Item*>(_listItem->objectAtIndex(i));
		item->updatePosition(dt);

		if (item->boundingBox().intersectsRect(_myPlant->boundingBox()))
		{
			item->getProcessor()->process(_myPlant, this);
			removeItem(item);
			continue;
		}

		if (!item->boundingBox().intersectsRect(_bulletArea))
		{
			removeItem(item);
			continue;
		}

		i++;
	}

	// PLANE
	if (_myPlant->getHealth() < 0)
	{
		endGame();
	}

	if (_map->isMapComplete() && _listEnemy->count() == 0)
	{
		runAction(CCSequence::create(CCDelayTime::create(2), CCCallFuncN::create(this, SEL_CallFuncN(&MainLayer::callbackEndGame)), NULL));
		//endGame();
	}
}

void MainLayer::onEnter()
{
	CCLayer::onEnter();
	schedule(SEL_SCHEDULE(&MainLayer::update));
	runAction(CCSequence::create(CCDelayTime::create(1), CCCallFuncN::create(this, SEL_CallFuncN(&MainLayer::startShoot)), NULL));
	_map->startMap();
	setKilomet(0);
}

void MainLayer::onExit()
{
	CCLayer::onExit();
	unschedule(SEL_SCHEDULE(&MainLayer::update));
}


void MainLayer::addItem( Item* item )
{
	if (!item)
		return;

	_listItem->addObject(item);
	addChild(item, ITEM_LAYER);
}

void MainLayer::removeItem( Item* item )
{
	_listItem->removeObject(item);
	removeChild(item);
}

void MainLayer::addEnemy( Enemy* enemy )
{
	if (!enemy)
		return;
	if (_listEnemy->containsObject(enemy))
		return;
	_listEnemy->addObject(enemy);
	addChild(enemy, PLANE_LAYER);
}

void MainLayer::removeEnemy( Enemy* enemy )
{
	if (!enemy)
		return;
	removeChild(enemy);
	_listEnemy->removeObject(enemy);
}

void MainLayer::removePlayerBullet( Bullet* bullet )
{
	_listPlayerBullet->removeObject(bullet);
	removeChild(bullet);
}

void MainLayer::addPlayerBullet( Bullet* bullet )
{
	if (_listPlayerBullet->containsObject(bullet))
		return;
	_listPlayerBullet->addObject(bullet);
	addChild(bullet, PLANE_LAYER);
}

void MainLayer::addEnemyBullet( Bullet* bullet )
{
	if (_listEnemyBullet->containsObject(bullet))
		return;

	_listEnemyBullet->addObject(bullet);
	addChild(bullet, PLANE_LAYER);
}

void MainLayer::startShoot( CCNode* sender )
{
	_myPlant->setWeaponLevel(GlobalData::sharedData()->getPlayerData()->getPlaneLevel());
	_pet1->setWeaponLevel(1);
	_pet2->setWeaponLevel(1);
}

void MainLayer::keyBackClicked()
{
	CCDirector::sharedDirector()->replaceScene(MainScene::scene());
}

int MainLayer::getScore()
{
	return _score;
}

void MainLayer::setScore(int val)
{
	_score = val;
	if (getInputLayer()->getLblScore())
		getInputLayer()->getLblScore()->setString(MathUtil::IntToString(_score).c_str());
}

int MainLayer::getStar()
{
	return _star;
}

void MainLayer::setStar(int var)
{
	_star = var;
	if (getInputLayer()->getLblStar())
		getInputLayer()->getLblStar()->setString(MathUtil::IntToString(_star).c_str());
}

float MainLayer::getKilomet()
{
	return _kilomet;
}

void MainLayer::setKilomet(float var)
{
	_kilomet = var;
	if (getInputLayer()->getLblKm())
		getInputLayer()->getLblKm()->setString(MathUtil::FloatToString(_kilomet, 2).c_str());
}

void MainLayer::pauseGame()
{
	_isPause = true;
 	pauseSchedulerAndActions();
	_myPlant->onExit();
	_pet1->onExit();
	_pet2->onExit();
	_enemyManager->onExit();
	_effectManager->onExit();
	_map->onExit();
	CCObject* it;
	CCARRAY_FOREACH(_listPlayerBullet, it)
	{
		dynamic_cast<Bullet*>(it)->onExit();
	}
	//onExit();
	getInputLayer()->setTouchEnabled(false);
}

void MainLayer::resumeGame()
{
	_isPause = false;
	//onEnter();
	resumeSchedulerAndActions();
	_myPlant->onEnter();
	_enemyManager->onEnter();
	_effectManager->onEnter();
	_map->onEnter();
	CCObject* it;
	CCARRAY_FOREACH(_listPlayerBullet, it)
	{
		dynamic_cast<Bullet*>(it)->onEnter();
	}

	getInputLayer()->setTouchEnabled(true);
}

InputLayer* MainLayer::getInputLayer()
{
	return dynamic_cast<InputLayer*>(getParent()->getChildByTag(INPUTLAYER_TAG));
}

void MainLayer::endGame()
{
	pauseGame();
	// disable pause button
	getInputLayer()->getPauseButton()->setEnabled(false);

	ResultDialog* dialog = ResultDialog::create();
	dialog->parseData(this);
	getInputLayer()->addChild(dialog, UI_LAYER);
}

void MainLayer::callbackEndGame( CCNode* sender )
{
	endGame();
}
